/*
 * Copyright (c) 2016. For Intelligent Group.
 */

package com.intelligent.ispc.core.service.impl;

import com.google.common.collect.Lists;
import com.intelligent.ispc.cache.GrrDataCacheFactory;
import com.intelligent.ispc.common.utils.ApplicationException;
import com.intelligent.ispc.common.utils.ExceptionMessages;
import com.intelligent.ispc.common.utils.ResourceBundleUtils;
import com.intelligent.ispc.common.utils.StringUtils;
import com.intelligent.ispc.constant.AppConstant;
import com.intelligent.ispc.core.repository.*;
import com.intelligent.ispc.core.dto.*;
import com.intelligent.ispc.core.entity.*;
import com.intelligent.ispc.core.service.FileDataService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.File;
import java.util.*;

/**
 * Created by Julia.Zhou on 2016/07/15.
 * Updated by Eligi.Ran on 2016/08/30 , updated method from "deleteAllFileDatas()" to "deleteAllFileDatas(String type)"
 * Updated by Eligi.Ran on 2016/09/01 , updated method "validateFileName(List<String> names, String type)"
 */
@Service
public class FileDataServiceImpl implements FileDataService {

    private final Logger logger = LoggerFactory.getLogger(FileDataServiceImpl.class);

    @Autowired
    private FileDataDao fileDataDao;

    @Autowired
    private GrrItemDao grrItemDao;

    @Autowired
    private FileDataService fileDataService;

    @Autowired
    private GrrDataCacheFactory grrDataCacheFactory;

    @Override
    public void createFileData(FileDataDto fileDataDto) {
        if (fileDataDto == null) {
            throw new ApplicationException(ExceptionMessages.ERR_15008, ResourceBundleUtils.getString(ExceptionMessages.EXCEPTION_GLOBAL_FILE_PARAMETER_INVALID));
        }

        FileData fileData = new FileData();
        BeanUtils.copyProperties(fileDataDto, fileData);
        fileData.setImportTime(new Date());
        fileDataDao.createFileData(fileData);
    }

    @Override
    public void importSpcData(List<KeyValueDto> filePath) {
        if (filePath == null || filePath.isEmpty()) {
            throw new ApplicationException(ExceptionMessages.ERR_15008, ResourceBundleUtils.getString(ExceptionMessages.EXCEPTION_GLOBAL_FILE_PARAMETER_INVALID));
        }
        for (KeyValueDto singleFile : filePath) {
            FileData fileData = new FileData();
            fileData.setDataType(AppConstant.FILE_IMPORT_TYPE_SPC);
            fileData.setName(singleFile.getKey());
            String savePath = singleFile.getValue().toString();
            fileData.setSavePath(savePath);
            fileData.setImportTime(new Date());
            fileDataDao.createFileData(fileData);
            logger.info("Created file data at: " + savePath);
        }
    }

    @Override
    public void importGrrData(List<KeyValueDto> filePath, String dimension) {
        if (filePath == null || filePath.isEmpty()) {
            throw new ApplicationException(ExceptionMessages.ERR_15008, ResourceBundleUtils.getString(ExceptionMessages.EXCEPTION_GLOBAL_FILE_PARAMETER_INVALID));
        }
        for (KeyValueDto keyValueDto : filePath) {
            FileData fileData = new FileData();
            fileData.setName(keyValueDto.getKey());
            fileData.setSavePath(keyValueDto.getValue().toString());
            fileData.setDataType(AppConstant.FILE_IMPORT_TYPE_GRR);
            fileDataDao.createFileData(fileData);

            GrrItem grrItem = new GrrItem();
            grrItem.setGrrName(keyValueDto.getKey());
            grrItem.setDimension(dimension);
            grrItemDao.createGrrItem(grrItem);
        }
    }


    @Override
    public List<FileDataDto> reloadData(String type) {
        if (StringUtils.isBlank(type)) {
            throw new ApplicationException(ExceptionMessages.ERR_15008, ResourceBundleUtils.getString(ExceptionMessages.EXCEPTION_GLOBAL_FILE_PARAMETER_INVALID));
        }
        List<FileDataDto> fileDataDtos = fileDataService.findFileData(type);
        List<FileDataDto> existFileDataDto = new ArrayList<>();
        if (fileDataDtos != null && !fileDataDtos.isEmpty()) {
            for (FileDataDto fileDataDto : fileDataDtos) {
                File file = new File(fileDataDto.getSavePath());
                if (!file.exists()) {
                    fileDataDao.deleteFileDataByName(file.getName(), type);
                } else {
                    existFileDataDto.add(fileDataDto);
                }
            }
        }
        if (type.equals(AppConstant.FILE_IMPORT_TYPE_GRR)) {
            grrDataCacheFactory.getCacheGrrViewData().invalidateAll();
        }
        logger.info("Reloaded all files");
        return existFileDataDto;
    }

    @Override
    public void updateFileData(FileDataDto fileDataDto) {
        if (fileDataDto == null || fileDataDto.getId() == null) {
            throw new ApplicationException(ExceptionMessages.ERR_15008, ResourceBundleUtils.getString(ExceptionMessages.EXCEPTION_GLOBAL_FILE_PARAMETER_INVALID));
        }
        FileData fileData = fileDataDao.findById(fileDataDto.getId());
        if (fileData == null) {
            throw new ApplicationException(ExceptionMessages.ERR_15007, ResourceBundleUtils.getString(ExceptionMessages.EXCEPTION_GLOBAL_OBJECT_INVALID));
        }
        fileDataDto.setId(fileData.getId());
        BeanUtils.copyProperties(fileDataDto, fileData);
        fileData.setUpdateTime(new Date());
        fileDataDao.updateFileData(fileData);
    }

    @Override
    public void updateGrrFileData(FileDataDto fileDataDto) {
        if (fileDataDto == null || fileDataDto.getId() == null) {
            throw new ApplicationException(ExceptionMessages.ERR_15008, ResourceBundleUtils.getString(ExceptionMessages.EXCEPTION_GLOBAL_FILE_PARAMETER_INVALID));
        }
        List<FileData> fileDatas = fileDataDao.findFileData(AppConstant.FILE_IMPORT_TYPE_GRR);
        if (fileDatas != null && !fileDatas.isEmpty()) {
            for (FileData fileData : fileDatas) {
                fileData.setCheck(false);
                if (fileData.getId().equals(fileDataDto.getId())) {
                    fileData.setCheck(true);
                }
                fileDataDao.updateFileData(fileData);
            }
        }
    }

    @Override
    public void updateSpcFileDatas(List<FileDataDto> fileDataDtos) {
        if (fileDataDtos == null || fileDataDtos.isEmpty()) {
            throw new ApplicationException(ExceptionMessages.ERR_15008, ResourceBundleUtils.getString(ExceptionMessages.EXCEPTION_GLOBAL_FILE_PARAMETER_INVALID));
        }
        for (FileDataDto dto:fileDataDtos) {
            FileData fileData = new FileData();
            BeanUtils.copyProperties(dto, fileData);
            fileData.setUpdateTime(new Date());
            fileDataDao.updateFileData(fileData);
        }
    }

    @Override
    public void deleteFileDataByName(String name, String type) {
        if (StringUtils.isBlank(name) && StringUtils.isBlank(type)) {
            throw new ApplicationException(ExceptionMessages.ERR_15008, ResourceBundleUtils.getString(ExceptionMessages.EXCEPTION_GLOBAL_FILE_PARAMETER_INVALID));
        }
        fileDataDao.deleteFileDataByName(name, type);
        List<String> keyList = null;
        if (type.equals(AppConstant.FILE_IMPORT_TYPE_GRR)) {
            grrItemDao.deleteGrrItemByName(name);

            keyList = Lists.newArrayList();
            Set<String> viewKeys = grrDataCacheFactory.getCacheGrrViewData().asMap().keySet();
            for (String key : viewKeys) {
                if (key.contains(name)) {
                    keyList.add(key);
                }
            }
            grrDataCacheFactory.getCacheGrrViewData().invalidateAll(keyList);
        }
    }

    @Override
    @Deprecated
    public void deleteFileDataByNames(List<String> names, String type) {
        Map<String, Object> params = new HashMap<>();
        params.put("names", names);
        params.put("type", type);
        fileDataDao.deleteFileDataByNames(params);
        if (type.equals(AppConstant.FILE_IMPORT_TYPE_GRR)) {
            grrItemDao.deleteGrrItemByNames(names);
        }
    }

    @Override
    public void deleteAllFileDatas(String type) {
        if (type.equals(AppConstant.FILE_IMPORT_TYPE_GRR)) {
            List<FileData> fileDatas = fileDataDao.findFileData(type);
            List<String> fileDataNames = new ArrayList<>();
            for (FileData fileData : fileDatas) {
                fileDataNames.add(fileData.getName());
            }
            grrItemDao.deleteGrrItemByNames(fileDataNames);
            fileDataDao.deleteAllFileDatas(type);
            grrDataCacheFactory.getCacheGrrViewData().invalidateAll();
        } else {
            fileDataDao.deleteAllFileDatas(type);
        }

    }

    @Override
    public FileDataDto findById(Long id) {
        if (id == null) {
            throw new ApplicationException(ExceptionMessages.ERR_15008, ResourceBundleUtils.getString(ExceptionMessages.EXCEPTION_GLOBAL_FILE_PARAMETER_INVALID));
        }
        FileData fileData = fileDataDao.findById(id);
        if (fileData == null) {
            throw new ApplicationException(ExceptionMessages.ERR_15007, ResourceBundleUtils.getString(ExceptionMessages.EXCEPTION_GLOBAL_OBJECT_INVALID));
        }
        FileDataDto fileDataDto = new FileDataDto();
        BeanUtils.copyProperties(fileData, fileDataDto);

        return fileDataDto;
    }

    @Override
    public FileDataDto findFileDataByNameAndType(String name, String type) {
        if (StringUtils.isBlank(name) || StringUtils.isBlank(type)) {
            throw new ApplicationException(ExceptionMessages.ERR_15008, ResourceBundleUtils.getString(ExceptionMessages.EXCEPTION_GLOBAL_FILE_PARAMETER_INVALID));
        }
        FileData fileData = fileDataDao.findByNameAndType(name, type);
        if (fileData == null) {
            throw new ApplicationException(ExceptionMessages.ERR_15007, ResourceBundleUtils.getString(ExceptionMessages.EXCEPTION_GLOBAL_OBJECT_INVALID));
        }
        FileDataDto fileDataDto = new FileDataDto();
        BeanUtils.copyProperties(fileData, fileDataDto);

        return fileDataDto;
    }

    @Override
    public List<FileDataDto> findFileData(String type) {
        if (StringUtils.isBlank(type)) {
            throw new ApplicationException(ExceptionMessages.ERR_15008, ResourceBundleUtils.getString(ExceptionMessages.EXCEPTION_GLOBAL_FILE_PARAMETER_INVALID));
        }
        List<FileData> fileDataList = fileDataDao.findFileData(type);
        List<FileDataDto> fileDataDtoList = Lists.newArrayList();
        if (fileDataList != null && !fileDataList.isEmpty()) {
            for (FileData fileData : fileDataList) {
                FileDataDto fileDataDto = new FileDataDto();
                BeanUtils.copyProperties(fileData, fileDataDto);
                fileDataDtoList.add(fileDataDto);
            }
        }

        return fileDataDtoList;
    }

    @Override
    public List<FileDataDto> validateFileName(List<String> names, String dataType) {
        if (names == null || dataType == null || names.size() == 0) {
            return null;
        }
        List<FileDataDto> fileDataDtoList = new ArrayList<>();
        for (String name : names) {
            FileData fileData = fileDataDao.findByNameAndType(name, dataType);
            if (fileData != null) {
                FileDataDto fileDataDto = new FileDataDto();
                BeanUtils.copyProperties(fileData, fileDataDto);
                fileDataDtoList.add(fileDataDto);
            }
        }
        return fileDataDtoList;
    }

}
